- MySQL除了为单个列值设置单列索引,也允许为多个列的组合设置索引,这种索引称为多列(组合 / 复合 / 联合)索引(Multiple-Column Indexes)。多列索引是将多个列综合起来建立的索引,可以在多种查询类型中快速定位所需数据,而不用分别建立多个单列索引
- 联合索引可以用于包含索引中所有列的查询条件的语句, 或者包含索引中的第一列的查询条件的语句, 以及索引中前两列, 索引中的前三列, 以此类推. 如果你在索引定义中以正确的顺序指定列, 那么联合索引就可以加速同一张表中的多个不同类型的查询
- MySQL可以使用多列索引来查询索引中所有列或只查询前几列的数据。创建一个多列索引(A, B, C),等同于建立了以下 3 种索引
- (A) -> (A)
- (A, B) -> (A),(B)
- (A, B, C) -> (A),(B) / (A),(C) / (A),(B),(C)
- 如果只需要查询 (A),(C),那么 MySQL 会在查询中进行优化,而不需要使用所有的 3 列。
- 如果 (C) 和 (D) 上存在多列索引,则可以直接提取相应的行。如果 (D) 和 (E) 上存在单独的单列索引,优化器会尝试使用索引合并优化,或者尝试通过决定哪个索引排除更多行并使用该索引提取行来找到限制性最强的索引
- 例如在一张表中有一个多列索引(last_name,first_name),在以下查询语句中,多列索引可以发挥作用
示例
SELECT * FROM test
WHERE last_name='Jones';
示例
SELECT *
FROM
test
WHERE
last_name='Jones'
AND
first_name='John';
示例
SELECT * FROM test
WHERE last_name='Jones'
AND (first_name='John' OR first_name='Jon');
示例
SELECT * FROM test
WHERE last_name='Jones'
AND first_name >='M' AND first_name < 'N';
- 上述多列索引也可以用于只指定 last_name 值的查询,因为该列是索引的最左边的一个索引
- 具体来说,当我们在定义多列索引时,可以将多个需要经常一起查询的字段都包括在多列索引中,这样当进行查询时,数据库就可以使用这个多列索引来快速定位数据,而不需要扫描整个表。这对于同一张表上的多种类型查询(例如聚合查询、分组查询、联合查询等)是十分有用的,因为不同类型的查询可能需要查询不同的字段,但是如果这些字段都包含在联合索引中,那么就可以快速定位数据。
- 当然,在不满足最左匹配原则时,查询不会使用多列索引
示例
SELECT * FROM test
WHERE first_name='John';
示例
SELECT *
FROM
test
WHERE
last_name='Jones'
OR
first_name='John';
注
- 索引最多可由16列组成。对于某些数据类型,可以为列的前缀编制索引(对于Blob和Text类型, 索引列可以取前几位, 如 INDEX( blob_col(10) )
- 在建立索引的时候,尽量在多个单列索引上判断是否可以使用联合索引。组合(复合 / 联合)的使用不仅可以节省空间,还可以更容易的使用到覆盖索引。
- 在创建多列索引的时候应该把频繁使用的列、区分度高的列放在前面,频繁使用代表索引利用率高,区分度高代表筛选力度大,也可以将常需要作为查询返回的字段增加到多列索引中,提高查询效率。
来自 <https://dev.mysql.com/doc/refman/8.0/en/multiple-column-indexes.html>